package com.cml.getway.core.context;

import com.cml.getway.common.config.Rule;
import com.cml.getway.common.util.AssertUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;

/**
 * 姓名：陈茂林
 * 时间：2024/1/8
 * 描述：
 */
public class GetwayContext extends BasicContext{
    private final GetwayRequest getwayRequest;

    private GetwayResponse getwayResponse;

    private final Rule rule;

    private GetwayContext(String protocol, ChannelHandlerContext nettyCtx, boolean keepAlive,
                          GetwayRequest getwayRequest, Rule rule) {
        super(protocol, nettyCtx, keepAlive);
        this.getwayRequest = getwayRequest;
        this.rule = rule;
    }

    public GetwayRequest getOriginRequest() {
        return getwayRequest;
    }

    public static class Builder {

        private String protocol;

        private ChannelHandlerContext nettyCtx;

        private GetwayRequest getwayRequest;

        private Rule rule;

        private boolean keepAlive;

        public Builder() {
        }

        public Builder setProtocol(String protocol) {
            this.protocol = protocol;
            return this;
        }

        public Builder setNettyCtx(ChannelHandlerContext nettyCtx) {
            this.nettyCtx = nettyCtx;
            return this;
        }

        public Builder setGetwayRequest(GetwayRequest getwayRequest) {
            this.getwayRequest = getwayRequest;
            return this;
        }

        public Builder setRule(Rule rule) {
            this.rule = rule;
            return this;
        }

        public Builder setKeepAlive(boolean keepAlive) {
            this.keepAlive = keepAlive;
            return this;
        }

        public GetwayContext build() {
            AssertUtil.notNull(protocol, "protocol不能为空");
            AssertUtil.notNull(nettyCtx, "nettyCtx不能为空");
            AssertUtil.notNull(getwayRequest, "rapidRequest不能为空");
            AssertUtil.notNull(rule, "rule不能为空");
            return new GetwayContext(protocol, nettyCtx, keepAlive, getwayRequest, rule);
        }
    }

    public <T> T getRequiredAttribute(AttributeKey<T> key) {
        T value = super.getAttribute(key);
        AssertUtil.notNull(value, "required attribute '" + key + "' is missing !");
        return value;
    }



    public <T> T getAttributeOrDefault(AttributeKey<T> key, T defaultValue) {
        return (T) attributes.getOrDefault(key, defaultValue);
    }

    public Rule.FilterConfig getFilterConfig(String filterId) {
        return rule.getFilterConfig(filterId);
    }

    public String getUniqueId() {
        return getwayRequest.getUniqueId();
    }

    public void releaseRequest() {
        if(requestReleased.compareAndSet(false, true)) {
            ReferenceCountUtil.release(getwayRequest.getFullHttpRequest());
        }
    }

    @Override
    public Rule getRule() {

        return rule;
    }

    public GetwayRequest getRequestMutale() {
        return getwayRequest;
    }

    @Override
    public GetwayRequest getRequest() {
        return getwayRequest;
    }

    @Override
    public GetwayResponse getResponse() {
        return getwayResponse;
    }

    @Override
    public void setResponse(Object response) {
        this.getwayResponse= (GetwayResponse) response;
    }
}
